package com.hzhq.contract.service.impl;

import com.hzhq.contract.bean.dto.RoleDTO;
import com.hzhq.contract.bean.entity.Role;
import com.hzhq.contract.convert.RoleConvertBasic;
import com.hzhq.contract.repo.DepartRepository;
import com.hzhq.contract.repo.RoleRepository;
import com.hzhq.contract.repo.UserRepository;
import com.hzhq.contract.repo.UserRoleRepository;
import com.hzhq.contract.service.RoleService;
import com.hzhq.contract.status.DefaultValue;
import com.hzhq.contract.util.Page2ResultUtil;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author: hzhq1255
 * @mail: hzhq1255@163.com
 * @date: 2021/4/15 20:08
 * @desc:
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    UserRoleRepository userRoleRepo;

    @Autowired
    UserRepository userRepo;

    @Autowired
    RoleRepository roleRepo;

    @Autowired
    DepartRepository departRepo;

    private Boolean isExisted(String roleName){
        Optional<Role> roleOptional = roleRepo.findByRoleNameAndDeleted(roleName, DefaultValue.NOT_DELETED);
        return roleOptional.isPresent();
    }

    private Boolean isExisted(ObjectId roleId){
        Optional<Role> roleOptional = roleRepo.findByRoleIdAndDeleted(roleId, DefaultValue.NOT_DELETED);
        return roleOptional.isPresent();
    }

    private Boolean isExisted(Integer roleType){
        Optional<Role> roleOptional = roleRepo.findByRoleCodeAndDeleted(roleType, DefaultValue.NOT_DELETED);
        return roleOptional.isPresent();
    }

    @Override
    public List<RoleDTO> getAllList() {
        List<Role> roleList = roleRepo.findByDeleted(DefaultValue.NOT_DELETED);
        return roleList.stream().map(RoleConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
    }

    @Override
    public Page<RoleDTO> getAllPage(Integer currentPage, Integer pageSize) {
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage,pageSize, Sort.by(Sort.Direction.DESC,"roleId"));
        Page<Role> rolePage = roleRepo.findByDeleted(DefaultValue.NOT_DELETED,pageable);
        return rolePage.map(RoleConvertBasic.INSTANCE::poToDto);
    }

    @Override
    public RoleDTO getOneByRoleId(String roleId) {
        if (ObjectId.isValid(roleId)){
            Optional<Role> roleOptional = roleRepo.findByRoleIdAndDeleted(new ObjectId(roleId),DefaultValue.NOT_DELETED);
            return roleOptional.map(RoleConvertBasic.INSTANCE::poToDto).orElse(null);
        }
        return null;
    }

    @Override
    public RoleDTO getOneByRoleName(String roleName) {
        Optional<Role> roleOptional = roleRepo.findByRoleNameAndDeleted(roleName,DefaultValue.NOT_DELETED);
        return roleOptional.map(RoleConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public RoleDTO getOneByRoleType(Integer roleType) {
        Optional<Role> roleOptional = roleRepo.findByRoleCodeAndDeleted(roleType,DefaultValue.NOT_DELETED);
        return roleOptional.map(RoleConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public RoleDTO update(RoleDTO roleDTO) {
        Optional<Role> roleOptional = roleRepo.findByRoleIdAndDeleted(roleDTO.getRoleId(),DefaultValue.NOT_DELETED);
        if (roleOptional.isPresent()) {
            Role updateRole = roleOptional.get();
            BeanUtils.copyProperties(RoleConvertBasic.INSTANCE.dtoToPo(roleDTO), updateRole);
            return RoleConvertBasic.INSTANCE.poToDto(roleRepo.save(updateRole));
        }
        return null;
    }

    @Override
    public RoleDTO save(RoleDTO roleDTO) {
        if ((!this.isExisted(roleDTO.getRoleName()) && (!this.isExisted(roleDTO.getRoleCode())))){
            Role role = roleRepo.save(RoleConvertBasic.INSTANCE.dtoToPo(roleDTO));
            return RoleConvertBasic.INSTANCE.poToDto(role);
        }
        return null;
    }

    @Override
    public List<RoleDTO> saveAll(List<RoleDTO> roleDTOList) {

        List<RoleDTO> saveList = roleDTOList.stream().filter(e -> !isExisted(e.getRoleCode()) && !isExisted(e.getRoleName())).collect(Collectors.toList());
        if (saveList.size() == roleDTOList.size()){
            List<Role> roleList = roleRepo.saveAll(saveList.stream().map(RoleConvertBasic.INSTANCE::dtoToPo).collect(Collectors.toList()));
            return roleList.stream().map(RoleConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
        }
        return null;
    }



    @Override
    public String deleteById(String roleId) {
        if (ObjectId.isValid(roleId)){
            Optional<Role> roleOptional = roleRepo.findByRoleIdAndDeleted(new ObjectId(roleId),DefaultValue.NOT_DELETED);
            if (roleOptional.isPresent()){
                Role role = roleOptional.get();
                role.setDeleted(DefaultValue.DELETED);
                roleRepo.save(role);
            }
            return roleOptional.map(e -> e.getRoleId().toString()).orElse(null);

        }
        return null;
    }

    @Override
    public String deleteByName(String roleName) {
        Optional<Role> roleOptional = roleRepo.findByRoleNameAndDeleted(roleName,DefaultValue.NOT_DELETED);
        if (roleOptional.isPresent()){
            Role role = roleOptional.get();
            role.setDeleted(DefaultValue.DELETED);
            roleRepo.save(role);
        }
        return roleOptional.map(e -> e.getRoleId().toString()).orElse(null);
    }



    @Override
    public List<String> deleteAll(List<String> roleIds) {
        List<ObjectId> objectIds = roleIds.stream().filter(ObjectId::isValid).map(ObjectId::new).collect(Collectors.toList());
        List<Role> roleList = roleRepo.findByDeletedAndRoleIdIn(DefaultValue.NOT_DELETED,objectIds)
                .stream().peek(e-> e.setDeleted(DefaultValue.DELETED)).collect(Collectors.toList());
        return roleRepo.saveAll(roleList).stream().map(e -> e.getRoleId().toString()).collect(Collectors.toList());
    }

    @Override
    public Page<RoleDTO> searchAllPages(RoleDTO roleDTO, Integer currentPage, Integer pageSize) {
        Role role = RoleConvertBasic.INSTANCE.dtoToPo(roleDTO);
        role.setDeleted(DefaultValue.NOT_DELETED);
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize,
                Sort.by(Sort.Direction.DESC,"roleId"));
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("roleName",ExampleMatcher.GenericPropertyMatchers.contains());
        Example<Role> roleExample = Example.of(role,exampleMatcher);
        return roleRepo.findAll(roleExample,pageable).map(RoleConvertBasic.INSTANCE::poToDto);
    }
}
